%load_ext pretty_jupyter

Introduction

The point of this notebook is to demonstrate the main features of Pretty Jupyter. This document, however, does not mean to repeat everything described on the wiki, rather than it means to show how to actually use it in practice.

Styling

As you can notice in the generated HTML document, the styles are quite different than the default. You can tweak them even more by classic <style> tag. The following cell does just that and it alters the header of this chapter.

%%html

<style>
    #Styling {
        font-weight: bold;
        font-family: Helvetica;
    }
</style>

JavaScript can be applied very similarly.

Table of Contents

One of the main capabilities is Table of Contents. It is automatically generated based on headers specified in Markdown or HTML (Markdown is recommended for safety). It can however be turned off by specifying in the notebook's metadata. We can view the main-features-demo.ipynb notebook as json and overwrite the following property to false:

"toc": true

Tabset

Another important functionality is the Tabset. It allows us to switch the tabs. It works the following way:

  1. On the line below some header we write the following: [//]: <X> (-.- tabset). Remove the X between < and >, it has been added for technical reasons.
  2. All sub-headers of this header and their content becomes tabbed content.

Tabset Root

To demonstrate this, we wrote this magical line under the Tabset Root header. And hence the following subsections will be tabbed.

Subsection 1

Content 1.

Subsection 2

Content 2 with some math:

$$ \frac{a^2}{a} = a$$

Subsection 3

Content 3.

The tabset is automatically ended by a header of same or higher magnitude. E.g. if tabset is on header <h2> (equivalent to ##), the it can be ended by <h1> or <h2>.

We can use this to our advantage and use an empty header element to just end the tabset such as this:

<h2 class="toc-ignore"></h2>

(toc-ignore class removes is from table of contents)

Markdown with Jinja

Another very important feature is so called Jinja Markdown. It allows us to combine Markdown with Python variables. It can even be combined with using Maths. It is demonstrated in the cells below:

a = 10
b = 3
%%jinja markdown

$$

\frac{a}{b} = \frac{ {{a}} }{ {{b}} } = {{ (a / b) | round(2) }}

$$
$$ \frac{a}{b} = \frac{ 10 }{ 3 } = 3.33 $$

To make a code cell a Jinja Markdown cell, its first line needs to have the following content:

%%jinja markdown

Then you write standard Markdown and when you want to use some variable, you specify e.g. {{ variable_name }}.

This concept is very powerful and can be used to display dynamically created tables or images, too. By default, the input of the Markdown is removed in the HTML document. This can, however, be overidden, see the docs.

%%jmd

Since Jinja Markdown cells are very common, instead of `%jinja markdown` we can write a shortcut: `%%jmd`.

Since Jinja Markdown cells are very common, instead of %jinja markdown we can write a shortcut: %%jmd.

Tables

Jinja Markdown is powerful enough to print e.g. Pandas tables as part of the markdown, and even hide them with <details> tag.

import pandas as pd

df = pd.DataFrame({"col1": [1, 2, 3], "col2": ["One", "Two", "Three"]})
%%jmd

<details open>
<summary>Details can be viewed inside.</summary>

{{ df.to_html() }}

</details>
Details can be viewed inside.
col1 col2
0 1 One
1 2 Two
2 3 Three

Plots

Even plots can be displayed as part of the Jinja Markdown. However, in order to do that, we need to create the image element manually, which is a bit tedious, however a useful helper function can be made.

import matplotlib.pyplot as plt
import seaborn as sns
sns.set_theme()

import base64
from io import BytesIO

IMG_FORMAT = r"<img src='data:image/png;base64,{encoded}' />"

tmpfile = BytesIO()

fig, ax = plt.subplots()
sns.countplot(x=df["col1"], ax=ax).set(title="Example Figure")
fig.savefig(tmpfile, format="png")
plt.close()

encoded = IMG_FORMAT.format(encoded=base64.b64encode(tmpfile.getvalue()).decode('utf-8'))
%%jmd

The figure is displayed below:

{{ encoded }}

And we can continue our text further here.

The figure is displayed below:

And we can continue our text further here.

We can do the same with Plotly or other interactive plotting frameworks.

import plotly.express as px

fig = px.bar(x=["a", "b", "c"], y=[1, 3, 2])
%%jmd

It is simple to use it with Jinja Markdown.

{{ fig.to_html(include_plotlyjs=False, full_html=False, default_height=400, default_width=600) }}

It is simple to use it with Jinja Markdown.

Code Folding

You might've noticed that there are a lot of Hide buttons on the right. This is a functionality called Code Folding. It allows us to hide and show code and results in a more dynamic and visually appealing report. There is also a button on the top with Code All that allows us to toggle all codes on or off.

This functionality can be tweaked in the notebook's metadata. There is the following property in this notebook's json (open it as text):

"code_folding": "show"

Value show means that all code cells inputs will be visible at the document load. If we specify value hide in there, then all codes will be hidden at the beginning (this is also default when the property is missing). Any other value will result in the Code Folding functionality being turned off, hence all inputs will be visible.

a = 10

Recommendations and Best Practices

Use Jinja Markdown instead of basic Markdown cell

You can hide the input using some kind of extension, so it will not bother you. And the added flexibility is very useful. And the shortcut magic %%jmd makes it very efficient.

Be very careful about HTML tags

HTML tags are very powerful way and can be used in combination with Markdown. However, if there is a Markdown equivalent, it should be favoured. If you make an error in the HTML tags in the wrong place (e.g. you forget to close <em> tag), it can have devastating effects on the output, since it messes up the DOM structure a lot.

Use headers in order

Do not use for example first #, then ### and then ##.Use them in a proper order. It's tempting to use lower header to have smaller letters, but the right way to do it is by styling the header element. Some bad orders can have a negative effect on the quality of the output.